# -*- coding: utf-8 -*-
"""
中性策略框架 | 邢不行 | 2024分享会
author: 邢不行
微信: xbx6660
"""
import time
import ccxt
import pandas as pd

from Functions import *
from Evaluate import *
import warnings

warnings.filterwarnings('ignore')

'''
对比步骤
1.从官网上下载一份最新的币种K线数据
2.修改config的end_time尽量为数据最新的时间
3.运行1号脚本和2号脚本得到策略选币结果和资金曲线

实盘数据准备
4.将服务器上的选币文件和资金曲线文件保存至本地
5.将保存至本地的数据路径在脚本中进行配置

进行对比
6.选币对比：
    6.1一次只能对比一个offset的回测选币
    6.2确保进行对比的策略是一致的
    6.3如果出现不一致的情况，可以先检查一下配置是否一致(比如选币数量、持仓周期等，以及非常重要的黑名单币种)
7.轮动因子值对比
    7.1一次只能对比一个offset的轮动因子值
    7.2回测轮动因子值应与实盘完全一致
8.资金曲线对比
    8.1回测为单offset资金曲线，实盘多offset混合的资金曲线，有一定差异是正常的，但差异不能过大
    8.2即便实盘跑的是单offset的策略，也无法做到实盘和回测的资金曲线完全一致，走势一致即可
'''

# =路径配置
shift_name = 'Shift_Example'  # 指定策略名
data_path = 'D:/pythonproject/coin/中性策略框架2.1.9/轮动策略框架/轮动策略实盘框架/data'  # 指定实盘的data文件夹路径
account_name = '账户1'  # 指定账户名
param = [7]  # 配置参数覆盖中的一组参数。如果是单因子，配置[7]；如果是双因子，配置[7,10]。不能指定参数覆盖的参数。

# =参数配置
n = 10  # 对比选币周期数，最多对比n个周期。从最新的数据开始对比，对比多少个周期
start_time = '2024-04-01'  # 设置资金曲线对比的开始时间
end_time = None  # 设置资金曲线对比的截止时间。可以为None，代表不设置截止时间
# 配置api获取转账记录
proxy = {}
# proxy = {'http': 'http://127.0.0.1:7890', 'https': 'http://127.0.0.1:7890'}
exchange_basic_config = {
    'apiKey': '',
    'secret': '',
    'timeout': 30000,
    'rateLimit': 10,
    'enableRateLimit': True,
    'options': {
        'adjustForTimeDifference': True,
        'recvWindow': 50000,
    },
    'proxies': proxy,
    'is_pure_long': False
}
# 获取对应账户的配置
exchange = ccxt.binance(exchange_basic_config)

# 动态读取config里面配置的strategy_name脚本
Shift = __import__('shift.%s' % shift_name, fromlist=('',))
# 获取Strategy的hold_period，后续使用
hold_period = Shift.hold_period
# 获取Strategy的offset
offset = Shift.offset

# 判断设置的参数列表是否与策略文件中的因子数量一致，如果出现不一致的情况则退出
if len(param) != len(Shift.factor_list):
    print('配置的参数数量与策略文件中的因子数量不一致，请检查配置')
    exit()

# 根据轮动因子列表得到轮动因子列名
factor_cols = []
_factor_list = []
param1 = ''
for index in range(len(param)):
    _para = param[index]
    factor_name = Shift.factor_list[index][0]
    if_reverse = Shift.factor_list[index][1]
    weight = Shift.factor_list[index][3]
    # 添加因子列名
    param1 += f'{_para}_'
    factor_cols.append(f'{factor_name}_{str(_para)}')
    _factor_list.append((factor_name, if_reverse, _para, weight))
param1 = param1[:-1]
param2 = str(_factor_list).replace(' ', '')

# =====获取当前服务器时区，距离UTC 0点的偏差
utc_offset = int(time.localtime().tm_gmtoff / 60 / 60)  # 如果服务器在上海，那么utc_offset=8

# 指定回测和实盘选币的路径。回测选币路径：1号脚本保存下来的轮动资金曲线文件；实盘选币路径：从服务器上下载下来并保存至对应实盘select_coin文件夹中的选币
test_select_coin = os.path.join(back_test_path, f"{shift_name.split('Shift_')[1]}_轮动资金曲线_{hold_period}_{offset}.csv")  # 回测选币数据
real_select_coin = os.path.join(data_path, account_name, 'select_coin/')  # 实盘选币数据(需要从服务器上下载下来)

# 指定回测和实盘因子值的路径。回测因子值路径：1好脚本保存下来的中间数据。实盘因子值路径：服务器上下载下来的strategy_info文件夹
inter_data = os.path.join(back_test_path, f"{shift_name.split('Shift_')[1]}_轮动策略中间数据_{hold_period}_{offset}.pkl")
factor_data = os.path.join(data_path, account_name, 'strategy_info', shift_name, f'offset{offset}_param{param1}.csv')

# 指定回测和实盘资金曲线的路径。回测资金曲线路径：1号脚本保存的资金曲线文件；实盘资金曲线路径：从服务器上下载下来的账户信息文件夹
test_curve = os.path.join(back_test_path, f"{shift_name.split('Shift_')[1]}_轮动资金曲线_{hold_period}_{offset}.csv")  # 回测资金曲线
real_curve = os.path.join(data_path, account_name, '账户信息/equity.csv')  # 实盘资金曲线(需要从服务器上下载下来)

# 选币对比
select_coin_compare(test_select_coin, real_select_coin, offset, n, hold_period, param2)

# 轮动因子值对比
factor_compare(inter_data, factor_data, factor_cols, start_time, hold_period)

# 资金曲线对比
curve_compare(exchange, real_curve, test_curve, data_path, account_name, utc_offset, start_time, end_time, root_path)
